﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Xml;

namespace Games.WPF.UI
{
    public class DesignerCanvas : Canvas
    {
        #region Constructors

        public DesignerCanvas()
            : base()
        {
            MouseDown += new MouseButtonEventHandler(DesignerCanvas_MouseDown);
            MouseMove += new MouseEventHandler(DesignerCanvas_MouseMove);
            Drop += new DragEventHandler(DesignerCanvas_Drop);

            SelectedItems = new List<DesignerItem>();
            AllowDrop = true;
        }


        #endregion

        #region Properties

        public List<DesignerItem> SelectedItems { get; set; }
        private Point? DragStartPoint { get; set; }

        #endregion

        #region Methods

        protected override Size MeasureOverride(Size constraint)
        {
            Size size = new Size();
            foreach (UIElement element in base.Children)
            {
                double left = Canvas.GetLeft(element);
                double top = Canvas.GetTop(element);
                left = double.IsNaN(left) ? 0 : left;
                top = double.IsNaN(top) ? 0 : top;

                //measure desired size for each child
                element.Measure(constraint);

                Size desiredSize = element.DesiredSize;
                if (!double.IsNaN(desiredSize.Width) && !double.IsNaN(desiredSize.Height))
                {
                    size.Width = Math.Max(size.Width, left + desiredSize.Width);
                    size.Height = Math.Max(size.Height, top + desiredSize.Height);
                }
            }
            // For aesthetic reasons add extra points:
            size.Width += 10;
            size.Height += 10;
            return size;
        }

        #endregion

        #region Event Handlers

        private void DesignerCanvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.Source == this)
            {
                DragStartPoint = new Point?(e.GetPosition(this));

                foreach (DesignerItem item in SelectedItems)
                {
                    item.IsSelected = false;
                }
                SelectedItems.Clear();

                e.Handled = true;
            }
        }

        private void DesignerCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed)
            {
                DragStartPoint = null;
            }

            if (DragStartPoint.HasValue)
            {
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
                if (adornerLayer != null)
                {
                    RubberbandAdorner adorner = new RubberbandAdorner(this, DragStartPoint);
                    if (adorner != null)
                    {
                        adornerLayer.Add(adorner);
                    }
                }
            }

            e.Handled = true;
        }

        private void DesignerCanvas_Drop(object sender, DragEventArgs e)
        {
            String xamlString = e.Data.GetData("DESIGNER_ITEM") as String;
            if (!String.IsNullOrEmpty(xamlString))
            {
                DesignerItem newItem = null;
                Object content = XamlReader.Load(XmlReader.Create(new StringReader(xamlString)));

                if (content != null)
                {
                    newItem = new DesignerItem();
                    newItem.Content = content;

                    //set position and size
                    Point position = e.GetPosition(this);
                    newItem.Width = 65;
                    newItem.Height = 65;
                    DesignerCanvas.SetLeft(newItem, Math.Max(0, position.X - newItem.Width / 2));
                    DesignerCanvas.SetTop(newItem, Math.Max(0, position.Y - newItem.Height / 2));
                    Children.Add(newItem);

                    //update selection
                    foreach (DesignerItem item in this.SelectedItems)
                    {
                        item.IsSelected = false;
                    }
                    SelectedItems.Clear();
                    newItem.IsSelected = true;
                    SelectedItems.Add(newItem);
                }

                e.Handled = true;
            }
        }

        #endregion
    }
}